package cn.quang.search.admin.service.impl;

import cn.quang.search.admin.entity.dto.Operator;
import cn.quang.search.admin.entity.dto.Result;
import cn.quang.search.admin.entity.po.*;
import cn.quang.search.admin.entity.vo.innerfetcher.SearchResultInnerFetcherFieldDicVO;
import cn.quang.search.admin.entity.vo.innerfetcher.SearchResultInnerFetcherRequest;
import cn.quang.search.admin.entity.vo.innerfetcher.SearchResultInnerFetcherWithFieldDicVO;
import cn.quang.search.admin.mapper.*;
import cn.quang.search.admin.service.ISearchResultInnerFetcherService;
import cn.quang.search.admin.service.common.RedisService;
import cn.quang.search.admin.utils.AssertUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author:  Entity Generator
 * @since:  2024-03-08 19:21:58
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SearchResultInnerFetcherService implements ISearchResultInnerFetcherService {

	private static final Logger logger = LoggerFactory.getLogger(SearchResultInnerFetcherService.class);
	private final SearchResultInnerFetcherMapper searchResultInnerFetcherMapper;
	private final SearchResultInnerFetcherFieldDicMapper searchResultInnerFetcherFieldDicMapper;
	private final SearchSceneMapper searchSceneMapper;
	private final SearchSceneInnerFetcherConfigMapper searchSceneInnerFetcherConfigMapper;
	private final SearchSceneInnerFetcherFieldConfigMapper searchSceneInnerFetcherFieldConfigMapper;
	
	private final SearchConfigChangeService searchConfigChangeService;
	private final RedisService redisService;

	private static final String LOCK_KEY = "CRM3$SEARCH_RESULT_INNER_FETCHER$";
	private static final int EXPIRE_SECONDS = 60;

//	@Override
//	public Result<Pagination<SearchResultInnerFetcherListItemVO>> list4View(Operator operator, SearchResultInnerFetcherQueryRequest request) {
//		Result<Pagination<SearchResultInnerFetcherListItemVO>> aopResult = new Result<>();
//
//		SearchGroup searchGroup = new SearchGroup(SearchLogicType.AND);
//		if(StringUtils.isNotBlank(request.getName())){
//			searchGroup.addSearch(SearchResultInnerFetcher.COL_NAME, SearchOperator.Equal, request.getName());
//		}
//		if(StringUtils.isNotBlank(request.getFuzzyClassName())){
//			searchGroup.addLike(SearchResultInnerFetcher.COL_CLASS_NAME, request.getFuzzyClassName());
//		}
//		if(StringUtils.isNotBlank(request.getStartCreateTime())){
//			Date startCreateTime = DateUtil.parse(request.getStartCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(SearchResultInnerFetcher.COL_CREATE_TIME, SearchOperator.GreaterThanOrEqual, startCreateTime);
//		}
//		if(StringUtils.isNotBlank(request.getEndCreateTime())){
//			Date endCreateTime = DateUtil.parse(request.getEndCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(SearchResultInnerFetcher.COL_CREATE_TIME, SearchOperator.LessThan, endCreateTime);
//		}
//		try {
//			Pagination<SearchResultInnerFetcher> entitiesPagination = this.searchResultInnerFetcherMapper.findEntitiesPagination(null, searchGroup, request.getPageIndex(), request.getPageSize(), String.format("%s desc", SearchResultInnerFetcher.COL_CREATE_TIME));
//			Pagination<SearchResultInnerFetcherListItemVO> pagination = new Pagination<>(request.getPageIndex(), request.getPageSize(), entitiesPagination.getTotalCount());
//			if(CollectionUtils.isNotEmpty(entitiesPagination)) {
//				for (SearchResultInnerFetcher innerFetcher : entitiesPagination) {
//					pagination.add(convertToListItemVo(innerFetcher));
//				}
//			}
//			return aopResult.changeSucc(pagination);
//		} catch (Exception e) {
//			logger.error("逻辑表查询失败", e);
//			return aopResult.changeErr("逻辑表查询失败：" + e.getMessage());
//		}
//	}

	/**
	 * 转换成列表视图
	 */
//	private SearchResultInnerFetcherListItemVO convertToListItemVo(SearchResultInnerFetcher innerFetcher) {
//		SearchResultInnerFetcherListItemVO vo = new SearchResultInnerFetcherListItemVO();
//		vo.setId(innerFetcher.getId());
//		vo.setClassName(innerFetcher.getClassName());
//		vo.setName(innerFetcher.getName());
//		vo.setDescription(innerFetcher.getDescription());
//		vo.setAsyncBoost(innerFetcher.getAsyncBoost() == DBConstants.DATA_TRUE ? "是" : "否");
//		vo.setCreatorName(BspService.getBspUserNameById(innerFetcher.getCreatorId()));
//		vo.setCreateTimeFormat(DateUtil.format(innerFetcher.getCreateTime()));
//		vo.setModifierName(BspService.getBspUserNameById(innerFetcher.getModifierId()));
//		vo.setModifyTimeFormat(DateUtil.format(innerFetcher.getModifyTime()));
//		return vo;
//	}

//	@Override
//	public Result<SearchResultInnerFetcherDetailVO> detail4View(Operator operator, long id) {
//		Result<SearchResultInnerFetcherDetailVO> aopResult = new Result<>();
//		try {
//			SearchResultInnerFetcher entity = searchResultInnerFetcherMapper.findEntityById(id);
//			return aopResult.changeSucc(convertToDetailVo(entity));
//		} catch (Exception e) {
//			logger.error(String.format("逻辑表(%s)查询失败", id), e);
//			return aopResult.changeErr("逻辑表详情查询失败：" + e.getMessage());
//		}
//	}

	/**
	 * 转换成详情
	 */
//	private SearchResultInnerFetcherDetailVO convertToDetailVo(SearchResultInnerFetcher entity) {
//		SearchResultInnerFetcherDetailVO vo = new SearchResultInnerFetcherDetailVO();
//		vo.setId(entity.getId());
//		vo.setClassName(entity.getClassName());
//		vo.setName(entity.getName());
//		vo.setDescription(entity.getDescription());
//		vo.setAsyncBoost(entity.getAsyncBoost() == DBConstants.DATA_TRUE);
//		// 开始读取关联的取数器字典
//		try {
//			List<SearchResultInnerFetcherFieldDic> fieldDices = searchResultInnerFetcherFieldDicMapper.selectByInnerFetcherId(entity.getId());
//			List<SearchResultInnerFetcherFieldDicVO> vos = Lists.newArrayList();
//			if(CollectionUtils.isNotEmpty(fieldDices)) {
//				for (SearchResultInnerFetcherFieldDic fieldDic : fieldDices) {
//					SearchResultInnerFetcherFieldDicVO fieldDicVO = new SearchResultInnerFetcherFieldDicVO();
//					fieldDicVO.setRequireFieldDescription(fieldDic.getRequireFieldDescription());
//					fieldDicVO.setRequireFieldName(fieldDic.getRequireFieldName());
//					vos.add(fieldDicVO);
//				}
//			}
//			vo.setInnerFetcherFieldDices(vos);
//		} catch (Exception e) {
//			logger.error("逻辑表关联的真实表获取失败", e);
//		}
//		return vo;
//	}

	@Override
	public Result<Long> add(Operator operator, SearchResultInnerFetcherRequest request) {
		Result<Long> aopResult = new Result<>();
		AssertUtils.argumentBlank(request.getClassName(), "必须提供类名");
		AssertUtils.argumentBlank(request.getName(), "必须提供内置取数器名称");
		AssertUtils.argumentBlank(request.getDescription(), "必须提供内置取数器描述");

		List<SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest> innerFetcherFieldDices = request.getInnerFetcherFieldDices();
		if(CollectionUtils.isEmpty(innerFetcherFieldDices)){
			innerFetcherFieldDices = Lists.newArrayList();
		}

		String className = request.getClassName();
		try {
			String uniqueKey = LOCK_KEY + className;
			String requestId = UUID.randomUUID().toString();
			if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)) {
				SearchResultInnerFetcher innerFetcher = searchResultInnerFetcherMapper.selectByClassName(className);
				if(innerFetcher != null) {
					return aopResult.changeErr(String.format("该内置取数器(%s)已经存在！", className));
				}
				// 添加内置取数器
				Date now = new Date();
				innerFetcher = new SearchResultInnerFetcher();
				innerFetcher.setClassName(request.getClassName());
				innerFetcher.setName(request.getName());
				innerFetcher.setDescription(request.getDescription());
				innerFetcher.setAsyncBoost(request.isAsyncBoost());
				innerFetcher.setCreatorId(operator.getOperatorId());
				innerFetcher.setCreateTime(now);
				innerFetcher.setModifierId(operator.getOperatorId());
				innerFetcher.setModifyTime(now);
				searchResultInnerFetcherMapper.insert(innerFetcher);
				long innerFetcherId = innerFetcher.getId();
				// 添加内置取数器和字典的对应关系
				if(CollectionUtils.isNotEmpty(innerFetcherFieldDices)) {
					for (SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest innerFetcherFieldDic : innerFetcherFieldDices) {
						SearchResultInnerFetcherFieldDic fieldDic = new SearchResultInnerFetcherFieldDic();
						fieldDic.setInnerFetcherId(innerFetcherId);
						fieldDic.setRequireFieldName(innerFetcherFieldDic.getRequireFieldName());
						fieldDic.setRequireFieldDescription(innerFetcherFieldDic.getRequireFieldDescription());
						fieldDic.setCreatorId(operator.getOperatorId());
						fieldDic.setCreateTime(now);
						fieldDic.setModifierId(operator.getOperatorId());
						fieldDic.setModifyTime(now);
						searchResultInnerFetcherFieldDicMapper.insert(fieldDic);
					}
				}
			} else {
				return aopResult.changeErr("操作过于频繁，请稍后重试");
			}
		} catch (Exception e) {
			logger.error("内置取数器添加失败", e);
			return aopResult.changeErr("内置取数器添加出现异常：" + e.getMessage());
		}
		return aopResult;
	}

	@Override
	public Result<?> update(Operator operator, long id, SearchResultInnerFetcherRequest request) {
		Result<?> aopResult = new Result<>();

		// 存储增删改的内置取数器字典名称，用于输出日志
		List<String> newInnerFetcherFieldDices = Lists.newArrayList();
		List<String> modifyInnerFetcherFieldDices = Lists.newArrayList();
		List<String> deleteInnerFetcherFieldDices = Lists.newArrayList();

		SearchResultInnerFetcher innerFetcher = searchResultInnerFetcherMapper.selectById(id);
		if(innerFetcher == null){
			return aopResult.changeErr("不存在该内置取数器！");
		}

		List<SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest> innerFetcherFieldDices = request.getInnerFetcherFieldDices();
		if(CollectionUtils.isEmpty(innerFetcherFieldDices)){
			innerFetcherFieldDices = Lists.newArrayList();
		}

		String uniqueKey = LOCK_KEY + (StringUtils.isBlank(request.getClassName()) ? innerFetcher.getClassName() : request.getClassName());
		String requestId = UUID.randomUUID().toString();
		if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)){
			try {
				if(StringUtils.isNotBlank(request.getClassName()) && !request.getClassName().equals(innerFetcher.getClassName())){
					SearchResultInnerFetcher existInnerFetcher = searchResultInnerFetcherMapper.selectByClassName(request.getClassName());
					if(existInnerFetcher != null){
						return aopResult.changeErr(String.format("系统内已存在类名称为(%s)的内置取数器！", request.getClassName()));
					}
				}
				Date now = new Date();
				innerFetcher.setClassName(StringUtils.isBlank(request.getClassName()) ? innerFetcher.getClassName() : request.getClassName());
				innerFetcher.setName(StringUtils.isBlank(request.getName()) ? innerFetcher.getName() : request.getName());
				innerFetcher.setDescription(StringUtils.isBlank(request.getDescription()) ? innerFetcher.getDescription() : request.getDescription());
				innerFetcher.setAsyncBoost(request.isAsyncBoost());
				innerFetcher.setModifierId(operator.getOperatorId());
				innerFetcher.setModifyTime(now);
				// 更新内置取数器
				searchResultInnerFetcherMapper.updateById(innerFetcher);
				// 更新与取数器字典的对应关系
				List<SearchResultInnerFetcherFieldDic> fieldDices = searchResultInnerFetcherFieldDicMapper.selectByInnerFetcherId(id);
				if(fieldDices == null) { fieldDices = Lists.newArrayList(); }
				Map<String, SearchResultInnerFetcherFieldDic> fieldDicMap = fieldDices.stream().collect(Collectors.toMap(SearchResultInnerFetcherFieldDic::getRequireFieldName, v -> v));
				Map<String, SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest> requestFieldDicMap = innerFetcherFieldDices.stream().collect(Collectors.toMap(SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest::getRequireFieldName, v -> v));

				List<Long> deleteIds = Lists.newArrayList();
				// 执行删除(需要校验内置取数器该字段是否已配置在场景内)
				for (SearchResultInnerFetcherFieldDic fieldDicRelation : fieldDices) {
					if(!requestFieldDicMap.containsKey(fieldDicRelation.getRequireFieldName())){
						List<SearchSceneInnerFetcherFieldConfig> sceneInnerFetcherFieldConfigs = searchSceneInnerFetcherFieldConfigMapper.selectByInnerFetcherFieldDicId(fieldDicRelation.getId());
						if(CollectionUtils.isNotEmpty(sceneInnerFetcherFieldConfigs)) {
							List<Long> sceneInnerFetcherConfigIds = sceneInnerFetcherFieldConfigs.stream().map(SearchSceneInnerFetcherFieldConfig::getSceneInnerFetcherConfigId).distinct().collect(Collectors.toList());
							List<SearchSceneInnerFetcherConfig> sceneInnerFetcherConfigs = searchSceneInnerFetcherConfigMapper.selectList(new QueryWrapper<SearchSceneInnerFetcherConfig>().lambda().in(SearchSceneInnerFetcherConfig::getId, sceneInnerFetcherConfigIds));
							List<Long> sceneIds = sceneInnerFetcherConfigs.stream().map(SearchSceneInnerFetcherConfig::getSceneId).distinct().collect(Collectors.toList());
							List<SearchScene> scenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
							if(CollectionUtils.isNotEmpty(scenes)) {
								return aopResult.changeErr(String.format("依赖字段(%s)存在关联的查询场景(%s)，请先在查询场景上取消该依赖字段的关联后再重试",
										String.format("%s(%s)", fieldDicRelation.getRequireFieldName(), fieldDicRelation.getRequireFieldDescription()), scenes.stream().map(input -> String.format("%s(%s)", input.getCode(), input.getName())).collect(Collectors.joining(", "))));
							}
						}
						deleteIds.add(fieldDicRelation.getId());
						deleteInnerFetcherFieldDices.add(fieldDicRelation.getRequireFieldName());
					}
				}
				for (Long deleteId : deleteIds) { searchResultInnerFetcherFieldDicMapper.deleteById(deleteId); }
				// 比较更新 ： 存在的更新，不存在的新增，未出现在请求中的删除
				for (SearchResultInnerFetcherRequest.SearchResultInnerFetcherFieldDicRequest fieldDicRequest : innerFetcherFieldDices) {
					SearchResultInnerFetcherFieldDic relation = fieldDicMap.get(fieldDicRequest.getRequireFieldName());
					if(relation != null){
						// 已存在的表，执行更新
						relation.setRequireFieldDescription(fieldDicRequest.getRequireFieldDescription());
						relation.setModifierId(operator.getOperatorId());
						relation.setModifyTime(now);
						searchResultInnerFetcherFieldDicMapper.updateById(relation);
						modifyInnerFetcherFieldDices.add(fieldDicRequest.getRequireFieldName());
					} else {
						// 新增
						relation = new SearchResultInnerFetcherFieldDic();
						relation.setInnerFetcherId(id);
						relation.setRequireFieldName(fieldDicRequest.getRequireFieldName());
						relation.setRequireFieldDescription(fieldDicRequest.getRequireFieldDescription());
						relation.setCreatorId(operator.getOperatorId());
						relation.setCreateTime(now);
						relation.setModifierId(operator.getOperatorId());
						relation.setModifyTime(now);
						searchResultInnerFetcherFieldDicMapper.insert(relation);
						newInnerFetcherFieldDices.add(fieldDicRequest.getRequireFieldName());
					}
				}
				searchConfigChangeService.triggerByInnerFetcher(id);
			} catch (Exception e){
				logger.error(String.format("内置取数器（%s）更新异常", id));
				return aopResult.changeErr("内置取数器更新失败，系统异常：" + e.getMessage());
			} finally {
				redisService.releaseLock(uniqueKey, requestId);
			}
		}

		logger.info(String.format("内置取数器关联依赖的字典描述：新增字典描述%s，修改字典描述%s，删除字典描述%s", newInnerFetcherFieldDices, modifyInnerFetcherFieldDices, deleteInnerFetcherFieldDices));
		return aopResult;
	}

	@Override
	public Result<?> delete(Operator operator, long id) {
		Result<?> aopResult = new Result<>();
		try {
			SearchResultInnerFetcher innerFetcher = searchResultInnerFetcherMapper.selectById(id);
			if(innerFetcher == null){
				return aopResult.changeErr("系统内已不存在该内置取数器！");
			}

			// 检查是否存在关联场景
			List<SearchSceneInnerFetcherConfig> sceneInnerFetcherConfigs = searchSceneInnerFetcherConfigMapper.selectByInnerFetcherId(id);
			if(CollectionUtils.isNotEmpty(sceneInnerFetcherConfigs)){
				List<Long> sceneIds = sceneInnerFetcherConfigs.stream().map(SearchSceneInnerFetcherConfig::getSceneId).distinct().collect(Collectors.toList());
				List<SearchScene> scenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
				return aopResult.changeErr("存在关联的查询场景：" + scenes.stream().map(input -> String.format("%s(%s)", input.getCode(), input.getName())).collect(Collectors.joining(", ")));
			}

			searchResultInnerFetcherMapper.deleteById(id);
			// 删除该逻辑表关联的自定义字典
			List<SearchResultInnerFetcherFieldDic> innerFetcherFieldDices = searchResultInnerFetcherFieldDicMapper.selectByInnerFetcherId(id);
			if(CollectionUtils.isNotEmpty(innerFetcherFieldDices)) {
				for (SearchResultInnerFetcherFieldDic innerFetcherFieldDic : innerFetcherFieldDices) {
					searchResultInnerFetcherFieldDicMapper.deleteById(innerFetcherFieldDic.getId());
				}
			}
		} catch (Exception e) {
			logger.error(String.format("删除内置取数器(%s)出现异常", id), e);
			return aopResult.changeErr("删除内置取数器出现系统异常：" + e.getMessage());
		}

		return aopResult;
	}

	/**
	 * 根据innerFetcherId获取字典
	 * @param operator 操作人
	 * @param innerFetcherId innerFetcherId
	 */
//	@Override
//	public Result<List<SearchResultInnerFetcherFieldDicVO>> fieldDices4View(Operator operator, long innerFetcherId) {
//		Result<List<SearchResultInnerFetcherFieldDicVO>> aopResult = new Result<>();
//		try {
//			List<SearchResultInnerFetcherFieldDic> searchResultInnerFetcherFieldDices = searchResultInnerFetcherFieldDicMapper.selectByInnerFetcherId(innerFetcherId);
//			List<SearchResultInnerFetcherFieldDicVO> vos = Lists.newArrayList();
//			if(CollectionUtils.isNotEmpty(searchResultInnerFetcherFieldDices)){
//				for (SearchResultInnerFetcherFieldDic fieldDic : searchResultInnerFetcherFieldDices) {
//					SearchResultInnerFetcherFieldDicVO vo = new SearchResultInnerFetcherFieldDicVO();
//					vo.setInnerFetcherFieldDicId(fieldDic.getId());
//					vo.setRequireFieldName(fieldDic.getRequireFieldName());
//					vo.setRequireFieldDescription(fieldDic.getRequireFieldDescription());
//					vos.add(vo);
//				}
//			}
//			return aopResult.changeSucc(vos);
//		} catch (Exception e) {
//			logger.error(String.format("根据内置取数器ID(%s)获取取数器字典失败", innerFetcherId), e);
//			return aopResult.changeErr("根据内置取数器获取取数器字典失败");
//		}
//	}

	@Override
	public Result<List<SearchResultInnerFetcherWithFieldDicVO>> listWithFieldDices(Operator operator) {
		Result<List<SearchResultInnerFetcherWithFieldDicVO>> aopResult = new Result<>();
		try {
			List<SearchResultInnerFetcherWithFieldDicVO> vos = Lists.newArrayList();
			List<SearchResultInnerFetcher> entities = searchResultInnerFetcherMapper.selectList(new QueryWrapper<>());
			if(CollectionUtils.isNotEmpty(entities)) {
				for (SearchResultInnerFetcher entity : entities) {
					SearchResultInnerFetcherWithFieldDicVO vo = new SearchResultInnerFetcherWithFieldDicVO();
					vo.setId(entity.getId());
					vo.setName(entity.getName());
					vo.setDescription(entity.getDescription());

					List<SearchResultInnerFetcherFieldDic> searchResultInnerFetcherFieldDices = searchResultInnerFetcherFieldDicMapper.selectByInnerFetcherId(entity.getId());
					List<SearchResultInnerFetcherFieldDicVO> fieldDicVos = Lists.newArrayList();
					if(CollectionUtils.isNotEmpty(searchResultInnerFetcherFieldDices)) {
						for (SearchResultInnerFetcherFieldDic fieldDic : searchResultInnerFetcherFieldDices) {
							SearchResultInnerFetcherFieldDicVO fieldDicVO = new SearchResultInnerFetcherFieldDicVO();
							fieldDicVO.setInnerFetcherFieldDicId(fieldDic.getId());
							fieldDicVO.setRequireFieldName(fieldDic.getRequireFieldName());
							fieldDicVO.setRequireFieldDescription(fieldDic.getRequireFieldDescription());
							fieldDicVos.add(fieldDicVO);
						}
					}
					vo.setFieldDices(fieldDicVos);
					vos.add(vo);
				}
			}
			return aopResult.changeSucc(vos);
		} catch (Exception e) {
			logger.error("获取带字典的内置取数器列表失败", e);
			return aopResult.changeErr("获取内置取数器列表失败");
		}
	}
}
